package com.psedu.base.service.impl;

import java.beans.Transient;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.psedu.base.domain.Apply;
import com.psedu.base.domain.vo.DivideGroupParam;
import com.psedu.base.domain.vo.GroupUserInfoVo;
import com.psedu.base.mapper.ApplyMapper;
import com.psedu.common.core.utils.BeanCopyUtils;
import com.psedu.common.core.utils.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.psedu.base.mapper.GroupMapper;
import com.psedu.base.domain.Group;
import com.psedu.base.service.IGroupService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 小组Service业务层处理
 * 
 * @author mingyue
 * @date 2022-03-07
 */
@Service
public class GroupServiceImpl implements IGroupService 
{
    @Autowired
    private GroupMapper groupMapper;

    @Autowired
    private ApplyMapper applyMapper;

    /**
     * 查询小组
     * 
     * @param groupId 小组主键
     * @return 小组
     */
    @Override
    public Group selectGroupByGroupId(Long groupId)
    {
        return groupMapper.selectGroupByGroupId(groupId);
    }

    /**
     * 查询小组列表
     * 
     * @param group 小组
     * @return 小组
     */
    @Override
    public List<Group> selectGroupList(Group group)
    {
        return groupMapper.selectGroupList(group);
    }

    /**
     * 新增小组
     * 
     * @param group 小组
     * @return 结果
     */
    @Override
    public int insertGroup(Group group)
    {
        group.setCreateTime(DateUtils.getNowDate());
        return groupMapper.insertGroup(group);
    }

    /**
     * 修改小组
     * 
     * @param group 小组
     * @return 结果
     */
    @Override
    public int updateGroup(Group group)
    {
        return groupMapper.updateGroup(group);
    }

    /**
     * 批量删除小组
     * 
     * @param groupIds 需要删除的小组主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteGroupByGroupIds(Integer[] groupIds)
    {
        for (Integer groupId : groupIds) {
            this.emptyGroup(groupId);
        }
        return groupMapper.deleteGroupByGroupIds(groupIds);
    }

    /**
     * 删除小组信息
     * 
     * @param groupId 小组主键
     * @return 结果
     */
    @Override
    public int deleteGroupByGroupId(Long groupId)
    {
        // 分组人员清空
        return groupMapper.deleteGroupByGroupId(groupId);
    }

    /**
     * 学期分组信息
     * @param semeId
     * @param deptId
     * @return
     */
    @Override
    public GroupUserInfoVo getUserGroupInfoBySemeId(Long semeId, Long deptId) {
        // 该部门该学期下的所有分组
        List<Group> groups = groupMapper.deptGroups(semeId, deptId);
        Map<Integer, Group> groupMap = new HashMap<>();
        for (Group group : groups) {
            groupMap.put(group.getGroupId(), group);
        }

        // 该部门、该学期的所有人
        List<Apply> applyList = applyMapper.selectDeptSemeStudent(semeId, deptId);
        List<GroupUserInfoVo.Student> allStudents = new ArrayList<GroupUserInfoVo.Student>();//BeanCopyUtils.copyList(applyList, GroupUserInfoVo.Student.class);
        for (Apply apply : applyList) {
            GroupUserInfoVo.Student student = new GroupUserInfoVo.Student();
            BeanUtils.copyProperties(apply, student);
            allStudents.add(student);
        }
        // 分出没分组的，已经分组的
        List<GroupUserInfoVo.Student> waitGroupStudents = new ArrayList<>();
        // groupId ： students
        Map<Integer, List<GroupUserInfoVo.Student>> groupStudentMap = new HashMap<>();
        for (Group group : groups) {
            groupStudentMap.put(group.getGroupId(), new ArrayList<GroupUserInfoVo.Student>());
        }
        for (GroupUserInfoVo.Student student : allStudents) {
            // 未分组
            Integer groupId = student.getGroupId();
            if (groupId == null || groupId == 0) {
                waitGroupStudents.add(student);
            // 已分组的放入Map
            } else {
                List<GroupUserInfoVo.Student> groupStudentList = groupStudentMap.get(groupId);
                groupStudentList.add(student);
            }
        }
        // 将学员分组Map转List
        List<GroupUserInfoVo.GroupStudent> groupStudentList = new ArrayList<>();
        for (Map.Entry<Integer, List<GroupUserInfoVo.Student>> entry : groupStudentMap.entrySet()) {
            Integer groupId = entry.getKey();
            List<GroupUserInfoVo.Student> studentList = entry.getValue();
            // 封装小组，小组下的所有学员
            GroupUserInfoVo.GroupStudent groupStudent = new GroupUserInfoVo.GroupStudent();
            groupStudent.setGroupId(groupId);
            Group group = groupMap.get(groupId);
            if(group != null && group.getGroupName() != null) {
                groupStudent.setGroupName(group.getGroupName());
            } else {
                groupStudent.setGroupName("无分组名称");
            }
            groupStudent.setStudentList(studentList);
            groupStudentList.add(groupStudent);
        }

        // 填充结果
        GroupUserInfoVo groupUserInfoVo = new GroupUserInfoVo();
        groupUserInfoVo
                .setSemeId(semeId)
                .setWaitUserList(waitGroupStudents)
                .setGroupStudentList(groupStudentList);


        return groupUserInfoVo;
    }

    /**
     * 学员分组修改
     * @param divideGroupParam
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void studentDivideGroup(DivideGroupParam divideGroupParam) {
        // 清空小组
        this.emptyGroup(divideGroupParam.getGroupId());
        // 分入小组
        if(divideGroupParam.getApplyIds() != null && divideGroupParam.getApplyIds().size() != 0) {
            applyMapper.divideGroup(divideGroupParam);
        }
    }

    public void emptyGroup(Integer groupId) {
        applyMapper.update(
                null,
                new LambdaUpdateWrapper<Apply>()
                        .set(Apply::getGroupId, null)
                        .eq(Apply::getGroupId, groupId)
        );
    }
}
